/**
 * *****************************************************************
 * @file    adt3102_pmu.c
 * @author  WuHao(hwu@andartechs.com.cn)
 * @version 1.0.0
 * @date    2020-11-09
 * @brief   
 *                 Copyright (c) 2020, Andar Technologies Inc.
 *                           www.andartechs.com 
 *
 * *****************************************************************
 */
/*------------------------------ include -------------------------------------*/
#include "adt3102_type_define.h"
#include "adt3102.h"
#include "adt3102_pmu.h"
#include "adt3102_gpio.h"
#include "adt3102_tx.h"
#include "adt3102_rx.h"
#include "adt3102_system.h"
#include "pmu_ctype_map.h"
#include "rfc_ctype_map.h"
#include "gpio_ctype_map.h"
extern uint32 g_phaseShftLut0;
extern uint32 g_phaseShftLut1;
volatile static uint8 s_sysFreq;

/*------------------------------ function ------------------------------------*/
/**
 * @brief   adt3102 power setting.
 * @param   onOroff: power on plli pll, plli vco, plln pll, plln vco, bb1 and bb2, 
 *                  bias1 and so on.
 * @return  None.
 * @note
 */
void adt3102PowerSw(int onOroff)
{   
    s_sysFreq = HIGH_CLOCK_50M;
    
    if(onOroff == 1)
    { 
		
	#if (EN_1V8_EXTERNAL == 1)
		baseband18LDO(DISABLE, BB_LDO_1P8, DISABLE, BB_LDO_1P8);
	#else 
		baseband18LDO(ENABLE, BB_LDO_1P8, DISABLE, BB_LDO_1P8);	
	    delayUs(50,HIGH_CLOCK);	 
        baseband18LDO(ENABLE, BB_LDO_1P8, ENABLE, BB_LDO_1P8);
	#endif
	    delayUs(50,HIGH_CLOCK);	
		
	#if (EN_1V8_EXTERNAL == 1)
		plliLDOEnable(DISABLE, DISABLE);
	#else
		plliLDOEnable(ENABLE, ENABLE);
	#endif	
	    delayUs(50,HIGH_CLOCK);
		
       
	#if (EN_1V8_EXTERNAL == 1)
		 pllnVcoConfig(DISABLE, PLLN_VCO_LDO_1P8);
	#else
		 pllnVcoConfig(ENABLE, PLLN_VCO_LDO_1P8);
	#endif		
	    delayUs(50,HIGH_CLOCK);	  
        pllnPllConfig(ENABLE, PLLN_PLL_LDO_2P5, ENABLE);
	    delayUs(50,HIGH_CLOCK);	  
        dacEnBias1Pd(ENABLE, POWER_ON);
	    delayUs(50,HIGH_CLOCK);
        //As a GPIO, P29 is conflict with debugMode, which would enable analog IF on P29.  
        //Add this to being compatible with some old version of PCB. 
        #if DEBUGMODE
        #else
            gpioOutput(29,1);  //must output 1, ant then set as output. so there is no glitch of P29's high level output.
            gpioDirection(29,0);
        #endif 
        gpioOutput(22,1);  //must output 1, ant then set as output. so there is no glitch of P29's high level output.
        gpioDirection(22,0);        
    }else{
		
	#if (EN_1V8_EXTERNAL == 1)
		plliLDOEnable(DISABLE, DISABLE);
	#else
		plliLDOEnable(DISABLE, ENABLE);
	#endif	

        pllnVcoConfig(DISABLE, PLLN_VCO_LDO_1P8);
        pllnPllConfig(DISABLE, PLLN_PLL_LDO_2P5, DISABLE);
        baseband18LDO(DISABLE, BB_LDO_1P8, DISABLE, BB_LDO_1P8);
        dacEnBias1Pd(DISABLE, POWER_DOWN);
    }
}


/**
 * @brief   select high_clk as 50MHz.
 * @param   None.
 * @return  None.
 * @note
 */
void switchTo50m(void)
{
    int32 regVal=0;
    int32 i;

    //-----------------------------------------------
    //--- switch to DCXO.
    //-----------------------------------------------
    regVal = PMU->pmu_clk_high_reg;
    regVal &= ~pmu_clk_high_reg_ctrl_high_clk_sel_mask << pmu_clk_high_reg_ctrl_high_clk_sel_shift;
    regVal |= 0x0 << pmu_clk_high_reg_ctrl_high_clk_sel_shift;
    PMU->pmu_clk_high_reg = regVal;
    delayUs(100, HIGH_CLOCK);
    for(i=0; i<10; i=i+1);

    s_sysFreq = HIGH_CLOCK_50M;
}


/**
 * @brief   select high_clk as 125MHz.
 * @param   None.
 * @return  None.
 * @note
 */
void switch_to_plli(void)
{
    int32 regVal=0;
    int32 i;

    // for adt301. turn on PLLI.
    //RFC->rfc_plli_ctrl_reg = 0xffffffff;

    //-----------------------------------------------
    //--- switch to plli.
    //-----------------------------------------------
    regVal = PMU->pmu_clk_high_reg;
    regVal &= ~pmu_clk_high_reg_ctrl_high_clk_sel_mask << pmu_clk_high_reg_ctrl_high_clk_sel_shift;
    regVal |= 0x1 << pmu_clk_high_reg_ctrl_high_clk_sel_shift;
    PMU->pmu_clk_high_reg = regVal;
    for(i=0; i<10; i=i+1);
    
    s_sysFreq = HIGH_CLOCK_125M;
}

uint8 getSystemFreq(void)
{
    return s_sysFreq;
}

/**
 * @brief   adt3102 mcu go to idle mode.
 * @param   None.
 * @return  None.
 * @note
 */
void mcuGotoIdle(void)
{
	  uint32 regTemp, regTemp2;
    //uint32 regTemp, regTemp2, regTemp3;
    
    regTemp = RFC->rfc_xo50m_cfg_reg;
    regTemp2 = RFC->rf_plli_daca_reg;
    //regTemp3 = soc_NVIC[soc_SETENA];
    
    // disable interrupt. 
//    soc_NVIC[soc_CLRENA] = 0xffffffff;        //disable all interrupt.   
//    setInterrupt(INT_DUALTIMER, ENABLEINT);   // for delayUs function.  
    setInterrupt(INT_RTC, ENABLEINT);           // enable RTC interrupt, to wake up MCU from IDLE mode. 
    // decrease hclk.     
    PMU->pmu_clk_high_reg |= 1<<7;        // mcu's hclk = 1/64 clk_high. 
    
    // close plli and ldo12_hp. 
    RFC->rf_plli_daca_reg = 0x0;
    PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_manu_ctrl_en_bit | pmu_pmu_ctrl_reg_ctrl_ldo12_pd_bit;
    RFC->rfc_xo50m_cfg_reg = 0x888;       
    delayUs(3,HIGH_CLOCK);              // delay about 100us.  Currently, hclk=1/64 clk_high, so 3 means 3*64 us. 
    
    // idle
    soc_SCR[0x0] = 0x00;
    __asm("WFI");
 
    // recovery plli and ldo12_hp. 
    PMU->pmu_pmu_ctrl_reg &= ~pmu_pmu_ctrl_reg_ctrl_ldo12_pd_bit;    
    RFC->rf_plli_daca_reg = regTemp2;    
    RFC->rfc_xo50m_cfg_reg = regTemp; 
    delayUs(3,HIGH_CLOCK);     // delay about 100us.  Currently, hclk=1/64 clk_high, so 3 means 3*64 us.
    PMU->pmu_pmu_ctrl_reg &= ~pmu_pmu_ctrl_reg_manu_ctrl_en_bit;  
    
    // recovery hclk
    PMU->pmu_clk_high_reg &= ~(1<<7);     // mcu's hclk = clk_high. 
 
    // recovery Interrupt.  
    //soc_NVIC[soc_SETENA] = regTemp3;    
       
    return;
}


/**
 * @brief   adt3102 mcu go to sleep.
 * @param   None.
 * @return  None.
 * @note
 */
void mcuGotoSleep(void)
{
    int32 regVal=0;

    //--- MUST check RTC's counter, making sure it will not wake up in 3 cycles.
    //

    //--- MUST make sure PMU's state is idle before going to sleep.
    regVal = PMU->pmu_pmu_state;
    regVal = regVal & (pmu_pmu_state_cur_state_mask << pmu_pmu_state_cur_state_shift);
    while( regVal != 0x00 )
    {
        regVal = PMU->pmu_pmu_state;
        regVal = regVal & (pmu_pmu_state_cur_state_mask << pmu_pmu_state_cur_state_shift);
    }

    // disable Manu mode, and configure sleeping registers.
    //PMU->pmu_pmu_ctrl_reg         &= ~pmu_pmu_ctrl_reg_manu_ctrl_en_bit ;
    //delayUs(100, HIGH_CLOCK) ; //10us for ASIC simulation, 100us for REAL CHIP.

    //

    soc_SCR[0x0] = 0x04;
    __asm("WFI");


    //--- Configure some registers after waking up.
    //--- Phase shifter
    //rfPhaseShift(0x1f, 0, 0x1f, 0);
}


/**
 * @brief   adt3102 setting for entering sleep mode.
 * @param   None.
 * @return  None.
 * @note
 */
void mcuSleepConfig(int32 ramOn)
{
    // ramOn = 0, sleep with PD_RAM off.
    // ramOn = 1, sleep with PD_RAM on, keep RAM powered on.

    //--- MUST enable all of clock gating cells. Otherwise, the sleep will fail.
    PMU->pmu_reg_ext_clk_en_reg = 0x0 ;
    
    //--- set por_test_sel = 1 avoid leakage, from Yuan.  
    RFC->rf_bias1_en_reg |= 1<<11; 

    //--- disable debugger's wake up function.
    //*(uint32*)0x4000c004 = 0x03;
    //PMU->pmu_int_en_reg &= ~(pmu_int_en_reg_ctrl_debug_wakeup_en_bit|pmu_int_en_reg_ctrl_rtc_wakeup_en_bit|pmu_int_en_reg_ctrl_io_wakeup_en_bit);
    PMU->pmu_int_en_reg = pmu_int_en_reg_ctrl_rtc_wakeup_en_bit | pmu_int_en_reg_ctrl_io_wakeup_en_bit;

    //--- set P29 as output, 1'h1.
    //*(uint32*)0x40020020 = 0x20000000;  // P29 output is high. .
    //*(uint32*)0x400200a4 = 0x01;  //    p29 as external LDO enable, for VDD_RF.
    //As a GPIO, P29 is conflict with debugMode, which would enable analog IF on P29. 
    //Add this to being compatible with some old version of PCB.    
    #if DEBUGMODE
    #else
        gpioOutput(29,1);  //must output 1, ant then set as output. so there is no glitch of P29's high level output.
        gpioDirection(29,0);
    #endif
        
    gpioOutput(22,1);  //must output 1, ant then set as output. so there is no glitch of P29's high level output.
    gpioDirection(22,0);


    // the time of IO_Wakeup to MCU_running = (powering_up_time+4)*T_32k.  0x99 means (153+4)*32us = 5ms appro.
    PMU->pmu_pmu_stage_time       = 0x010099;

    PMU->pmu_slp_xo50m_cfg        = 0x0 ;
    PMU->pmu_slp_plli_ctrl_reg    = 0x0 ;
    PMU->pmu_slp_ldo_bg_reg_reg   = 0x0 ;

    //0x7:1.3v.   0x0:1.2v,   0x6:1.1v,   0x5:1.0v,    0x4:0.85v,   0x3:0.8v,   0x2:0.75v.   0x1:0.7v,
    PMU->pmu_slp_ldo12n_rega_reg  = 0x3 << pmu_slp_ldo12n_rega_reg_slp_ldo12_lp_vcfg_shift ;//   0x1800; //0x1800 ;   //0x400 is 0.7v.

    if(ramOn) {
        PMU->pmu_slp_power_ctrl_reg   = 0x1f ;
    }
    else {
        PMU->pmu_slp_power_ctrl_reg   = 0x07 ;
//--- for leakage analysis.
//				PMU->pmu_slp_power_ctrl_reg   = 0x04 ;  //bg_33 = bg_18 = on.
//				PMU->pmu_pmu_ctrl_reg |=  pmu_pmu_ctrl_reg_ctrl_ldo18bb1_on_bit | pmu_pmu_ctrl_reg_ctrl_ldo18bb2_on_bit;
//			  PMU->pmu_slp_plli_ctrl_reg |= (1<<9 | 1<<10 | 1<<11 | 1<<12);
//			  RFC->rf_plln_ctrl_reg = 0x7;
//
//				PMU->pmu_pmu_ctrl_reg |= 1 << 4;
//				RFC->rfc_plli_ctrl_reg |= (1<<9 | 1<<10 | 1<<11 | 1<<12);
//			  delayUs(100, HIGH_CLOCK);
//				PMU->pmu_pmu_ctrl_reg &= ~(1 << 4);
//
//				PMU->pmu_sram_cfg &= ~pmu_sram_cfg_sram_retn_sel_bit;
//				PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_ctrl_hold_ana_cfg_bit;

    }

    //--- turn on clk_50m out, at an analog IO.
    //RFC->rfc_plli_ctrl_reg |= rfc_plli_ctrl_reg_xo50m_en_refclk_out_bit;
    //PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_manu_ctrl_en_bit;
    //delayUs(100,HIGH_CLOCK);
    //PMU->pmu_pmu_ctrl_reg &= ~pmu_pmu_ctrl_reg_manu_ctrl_en_bit;

}
void turnOnPlli(void)
{
    int32 regVal;
    regVal = 0xfffffff;
    regVal &= ~(rfc_plli_ctrl_reg_plli_en_ckdig_125m_bit | rfc_plli_ctrl_reg_plli_en_ckadc_bit | rfc_plli_ctrl_reg_xo50m_en_ckbist_bit | rfc_plli_ctrl_reg_xo50m_mode_bit);
    RFC->rfc_plli_ctrl_reg = regVal;
    regVal= RFC->rf_plli_rega_reg;
    regVal &= ~(rf_plli_rega_reg_plli_reg1_mask<<rf_plli_rega_reg_plli_reg1_shift);
    regVal |= 0xff<<rf_plli_rega_reg_plli_reg1_shift;
    RFC->rf_plli_rega_reg = regVal;

    PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_manu_ctrl_en_bit;
    for(int32 i=0 ; i<1000; i++) {}
    RFC->rfc_plli_ctrl_reg |= rfc_plli_ctrl_reg_plli_en_ckdig_125m_bit| rfc_plli_ctrl_reg_plli_en_ckadc_bit;

    PMU->pmu_pmu_ctrl_reg &= ~pmu_pmu_ctrl_reg_manu_ctrl_en_bit;
    RFC->rf_plli_rega_reg |= 1 <<(rf_plli_rega_reg_plli_reg2_shift + 3);
}


/**
 * @brief   adt3102 low power mode, open or close plli or plln.
 *              ________                                           ________
 *   |      |        |                                         |        |
 *   |      |        |                                         |        |
 *   |     	|        |                                         |        |
 *   |     	|        |                                         |        |
 *   |     	|        |_________                                |        |_________
 *   |      |        |         |                               |        |         |
 *   |      |        |         |                               |        |         |
_____|______|________|_________|_______________________________|________|_________|________
 *   |         radio    active                  sleep
 *   |
 *   |
 * @param   plliOn :  open or close plli vco.
 * @param   pllnOn :  open or close plln vco.
 * @return  None.
 * @note
 */
void lowPowerSwitchPll(int32 plliOn,int32 pllnOn)
{
    plliConfig(plliOn);
    pllnConfig(pllnOn);
    if((plliOn==1) || (pllnOn==1))
    {
        delayUs(50,HIGH_CLOCK); //wait for plli&plln settle
    }
}


/**
 * @brief   adt3102 in the low power consumption mode, the module that can not be 
                    switched in a short time needs a long stable time.
 * @param   rx0En:  rx0 enable.
 * @param   rx1En:  rx1 enable.
 * @param   tx0En:  tx0 enable.
 * @param   tx1En:  tx1 enable.
 * @param   tiaHpf: tia hpf enable(tia0 and tia1).
 * @param   rcHpf:  rc hpf enable(rx0 and rx1).
 * @param   pgaHpf: pga hpf enable(pga0 and pga1).
 * @return  None.
 * @note
 */
void lowPowerSwitchFast(int32 rx0En, int32 rx1En, int32 tx0En, int32 tx1En, uint32 tiaHpf,uint32 rcHpf, uint32 pgaHpf)
{
    int32 dacPower=0;
    int32 biasRx0=rx0En*8;
    int32 biasRx1=rx1En*8;
    int32 anyRxTx=rx0En | rx1En | tx0En | tx1En;
    int32 biasAnyRxTx=anyRxTx*8;
    if(anyRxTx==1)
    {
        dacPower=POWER_ON;
    }
    else
    {
        dacPower=POWER_DOWN;
    }
    dacEnBias1Pd(anyRxTx, dacPower); //all bias except for PA&LNA
    //bias2_en: enable signal for ztc bias for BB
    baseBandBiasSetting(rx0En | rx1En);    
    //------------------------ RX ------------------ //
    //turn on tia pga    
    rfTiaEnable(rx0En, rx1En);
    rfTiaDacBias(biasRx0|biasRx1, biasRx0|biasRx1);
    rfVgaEnable(rx0En, rx1En);
    rfVgaDacBias(biasRx0|biasRx1, biasRx0|biasRx1);
    pgaHpfConfig(rx0En, rx1En, pgaHpf, pgaHpf);
    //turn on adc, gpadc
    adcEnable(rx0En|rx1En, rx1En);
    adcBiasSetting(biasRx0, biasRx0, biasRx0, biasRx0, biasRx0, biasRx0, biasRx1, biasRx1, biasRx1, biasRx1, biasRx1, biasRx1);
    //RF RX
    rxLnaEnable(rx0En, rx1En);
    mixerEnable(rx0En, rx1En);
    //------------------------ common setting ------------------ //
    //enable 20G and doubler
    rfbuff20G(rx0En | rx1En | tx0En | tx1En, rx0En | rx1En | tx0En | tx1En);
    //enable buffer1to4
    rfBuff77GEnable(anyRxTx, tx0En, tx1En, rx0En, rx1En);
    //enable bias for 20G(fmcw buffer), doubler and buffer1to4
    bias20GTo80G(biasAnyRxTx, biasAnyRxTx, biasAnyRxTx, biasAnyRxTx, biasAnyRxTx, biasAnyRxTx, biasAnyRxTx, biasAnyRxTx);
    //------------------------ TX ------------------ //
    txPaEnable(tx0En, tx1En);
}


/**
 * @brief   adt3102 in the low power consumption mode, the module that can be 
                    switched in a short time needs a short stable time.
 * @param   rx0En: rx0 enable.
 * @param   rx1En: rx1 enable.
 * @param   tx0En: tx0 enable.
 * @param   tx1En: tx1 enable.
 * @return  None.
 * @note
 */
/* If the version you are currently using is V1.5.0(the main.c header file has 
    instructions), then you need to use the second function, if you are using
    the old version, use the first. */
#ifndef COMPATIBLE
void lowPowerSwitchSlow(int32 rx0En, int32 rx1En, int32 tx0En, int32 tx1En)
{
    int32 anyRxTx=rx0En | rx1En | tx0En | tx1En;
    if(anyRxTx==0)
    {
        //--- set P29 as output, 1'h0.
        gpioOutput(22,0);
        //As a GPIO, P29 is conflict with debugMode, which would enable analog IF on P29.  
        //Add this to being compatible with some old version of PCB.    
        #if DEBUGMODE
        #else
            gpioOutput(29,0);
        #endif
        pllnVcoConfig(0, PLLN_VCO_LDO_1P8);
        pllnPllConfig(0, PLLN_PLL_LDO_2P5, 0);
        baseband18LDO(0, BB_LDO_1P8, 0, BB_LDO_1P8);
        plliLDOEnable(0, 0);
        
        //--- optimization for active mode. 
        RFC->rfc_xo50m_cfg_reg = 0x888; 
        RFC->rf_plli_daca_reg = 0x0;  
        //PMU->pmu_clk_gate_reg = 0x0; //close all submodule's clock.   
        // when 50Mhz, close ldo12_hp.  ldo12_lp could support less than 12mA. 
        if(HIGH_CLOCK == HIGH_CLOCK_50M){
            PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_ctrl_ldo12_pd_bit;   
        }      
        PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_manu_ctrl_en_bit;
        delayUs(100,HIGH_CLOCK);
        PMU->pmu_pmu_ctrl_reg &= ~pmu_pmu_ctrl_reg_manu_ctrl_en_bit;        
    }
    else
    {
        gpioOutput(22,1);
        //As a GPIO, P29 is conflict with debugMode, which would enable analog IF on P29.  
        //Add this to being compatible with some old version of PCB.   
        #if DEBUGMODE
        #else
            gpioOutput(29,1);
        #endif
            
        delayUs(200,HIGH_CLOCK);
        plliLDOEnable(ENABLE, ENABLE);
        delayUs(100,HIGH_CLOCK);  //100us for 10uF cap on board
        pllnVcoConfig(1, PLLN_VCO_LDO_1P8);
        delayUs(100,HIGH_CLOCK);
        pllnPllConfig(1, PLLN_PLL_LDO_2P5, anyRxTx);
        delayUs(100,HIGH_CLOCK);
        baseband18LDO(rx0En, BB_LDO_1P8, 0, BB_LDO_1P8);
        delayUs(100,HIGH_CLOCK);
        baseband18LDO(rx0En, BB_LDO_1P8, rx1En, BB_LDO_1P8);
        delayUs(100,HIGH_CLOCK);
        rfPhaseShiftLUT(g_phaseShftLut0, g_phaseShftLut1);
        
        //--- recovery for radio mode. 
        RFC->rfc_xo50m_cfg_reg = 0x8F8; 
        RFC->rf_plli_daca_reg = 0x14aaa8;  
        //PMU->pmu_clk_gate_reg = 0x3ff; //close all submodule's clock.         
        if(HIGH_CLOCK == HIGH_CLOCK_50M){
            PMU->pmu_pmu_ctrl_reg &= ~pmu_pmu_ctrl_reg_ctrl_ldo12_pd_bit;   // when 50Mhz, close ldo12_hp. 
        }            
        PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_manu_ctrl_en_bit;
        delayUs(100,HIGH_CLOCK);
        PMU->pmu_pmu_ctrl_reg &= ~pmu_pmu_ctrl_reg_manu_ctrl_en_bit;        
    }
}
#else
void tmp_lowPowerSwitchSlow(int32 rx0En, int32 rx1En, int32 tx0En, int32 tx1En, AnalogDataStrTypedef *pDataStr)
{
    int32 anyRxTx=rx0En | rx1En | tx0En | tx1En;
    if(anyRxTx==0)
    {
        //--- set P29 as output, 1'h0.
        gpioOutput(22,0);
        //As a GPIO, P29 is conflict with debugMode, which would enable analog IF on P29. 
        //Add this to being compatible with some old version of PCB.          
        #if DEBUGMODE
        #else
            gpioOutput(29,0);
        #endif
        
        pllnVcoConfig(0, PLLN_VCO_LDO_1P8);
        pllnPllConfig(0, PLLN_PLL_LDO_2P5, 0);
        baseband18LDO(0, BB_LDO_1P8, 0, BB_LDO_1P8);
        plliLDOEnable(0, 0);
        
        //--- optimization for active mode. 
        RFC->rfc_xo50m_cfg_reg = 0x888; 
        RFC->rf_plli_daca_reg = 0x0;  
        //PMU->pmu_clk_gate_reg = 0x0; //close all submodule's clock.   
        // when 50Mhz, close ldo12_hp.  ldo12_lp could support less than 12mA. 
        if(HIGH_CLOCK == HIGH_CLOCK_50M){
            PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_ctrl_ldo12_pd_bit;   
        }      
        PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_manu_ctrl_en_bit;
        delayUs(100,HIGH_CLOCK);
        PMU->pmu_pmu_ctrl_reg &= ~pmu_pmu_ctrl_reg_manu_ctrl_en_bit;        
    }
    else
    {
        gpioOutput(22,1);
        //As a GPIO, P29 is conflict with debugMode, which would enable analog IF on P29.  
        //Add this to being compatible with some old version of PCB.
        #if DEBUGMODE
        #else
            gpioOutput(29,1);
        #endif
        
        delayUs(200,HIGH_CLOCK);
        plliLDOEnable(ENABLE, ENABLE);
        delayUs(100,HIGH_CLOCK);  //100us for 10uF cap on board
        pllnVcoConfig(1, PLLN_VCO_LDO_1P8);
        delayUs(100,HIGH_CLOCK);
        pllnPllConfig(1, PLLN_PLL_LDO_2P5, anyRxTx);
        delayUs(100,HIGH_CLOCK);
        baseband18LDO(rx0En, BB_LDO_1P8, 0, BB_LDO_1P8);
        delayUs(100,HIGH_CLOCK);
        baseband18LDO(rx0En, BB_LDO_1P8, rx1En, BB_LDO_1P8);
        delayUs(100,HIGH_CLOCK);
        rfPhaseShiftLUT(pDataStr->phaseShftLut0En, pDataStr->phaseShftLut1En);
        
        //--- recovery for radio mode. 
        RFC->rfc_xo50m_cfg_reg = 0x8F8; 
        RFC->rf_plli_daca_reg = 0x14aaa8;  
        //PMU->pmu_clk_gate_reg = 0x3ff; //close all submodule's clock.         
        if(HIGH_CLOCK == HIGH_CLOCK_50M){
            PMU->pmu_pmu_ctrl_reg &= ~pmu_pmu_ctrl_reg_ctrl_ldo12_pd_bit;   // when 50Mhz, close ldo12_hp. 
        }            
        PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_manu_ctrl_en_bit;
        delayUs(100,HIGH_CLOCK);
        PMU->pmu_pmu_ctrl_reg &= ~pmu_pmu_ctrl_reg_manu_ctrl_en_bit;        
    }
}
#endif


/**
 * @brief   set adt3102 gpio is hz.
 * @param   None.
 * @return  None.
 * @note
 */
void adt3102GpioHz(void)
{
    gpioDirection(GPIO0 , 2);
    gpioDirection(GPIO1 , 2);
    gpioDirection(GPIO2 , 2);
    gpioDirection(GPIO3 , 2);
    gpioDirection(GPIO4 , 2);
    gpioDirection(GPIO5 , 2);
    gpioDirection(GPIO6 , 2);
    gpioDirection(GPIO7 , 2);
    gpioDirection(GPIO8 , 2);
    gpioDirection(GPIO9 , 2);
    gpioDirection(GPIO10, 2);
    gpioDirection(GPIO11, 2);
    gpioDirection(GPIO12, 2);
    gpioDirection(GPIO13, 2);
    gpioDirection(GPIO14, 2);
    gpioDirection(GPIO15, 2);
    gpioDirection(GPIO16, 2);
    gpioDirection(GPIO17, 2);
    gpioDirection(GPIO18, 2);
    gpioDirection(GPIO19, 2);
    gpioDirection(GPIO20, 2);
    gpioDirection(GPIO21, 2);
    gpioDirection(GPIO22, 2);
    gpioDirection(GPIO23, 2);
    gpioDirection(GPIO24, 2);
    gpioDirection(GPIO25, 2);
    gpioDirection(GPIO26, 2);
    gpioDirection(GPIO27, 2);
    gpioDirection(GPIO28, 2);
    gpioDirection(GPIO29, 2);
    gpioDirection(GPIO30, 2);
}


/**
 * @brief   rc 32KHz osc output to gpio30.
 * @param   None.
 * @return  None.
 * @note
 */
void rc32kOutputP30(void)
{
    //gpio mux to output
    GPIO->gpio_p30_config = 5;
    //RFC->rf_rc32k_reg_reg = 0x0A;
}

/**
 * @brief   setting gpio for mcu weekup.
 * @param   pinNumber: gpio number id, 0~30.
 * @param   pinPolarity: wake up edge of gpio.
 *                      0: high level to wake up
 *                      1: low level to wake up.
 * @return  None.
 * @note
 */
void pmuGpioWakeup(uint32 pinNumber, uint32 pinPolarity)
{
    // set as input
    *((uint32*)(GPIO_REGS + pinNumber + 12)) = 0x30;
    // wake up enable.
    GPIO->gpio_wake_en |= 1<<pinNumber;
    // set polarity.
    if(pinPolarity) {
        GPIO->gpio_wake_pol |= 1<<pinNumber;
    }
    else {
        GPIO->gpio_wake_pol &= ~(1<<pinNumber);
    }
}

/**
 * @brief   adjust the calibration parameters to make rc32KHz close to 32.768KHz.
 *          rf_rc32k_reg_reg is a (sign+abs) format value to control rc32k's frequency.
 *             for example, 0x3f is the smallest frequency.  0x1f is the largest frequency.
 *             0x20 is close to 0x0, but smaller than 0x0.
 * @param   None.
 * @return  None.
 * @note
 */
void rc32kCalibration(void)
{
    int i;
    uint32 regVal;
    uint32 index;

    PMU->pmu_reg_ext_clk_en_reg &= ~pmu_reg_ext_clk_en_reg_cnr_high_ext_en_bit;
    PMU->pmu_clk_gate_reg |= pmu_clk_gate_reg_ctrl_clk_cali_en_bit;
    PMU->pmu_soft_reset_reg |= pmu_soft_reset_reg_ctrl_rst_cali_n_bit;
    //PMU->pmu_rc32k_calibration_reg = 0x5;
    PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_rc32k_cali_en_bit;

    //--- Try all setting and find the best one making 32k_prd = 0x5f5e, which is 32.768khz.
    //--- F_32k = 64/32k_prd*50mhz/4 = 32.768khz, so 32k_prd = 0x5f5e.
//    PMU->pmu_rc32k_calibration_reg = 0x5;
//    delayUs(100,HIGH_CLOCK);
//    for(i=0;i<64;i=i+1){
//        RFC->rf_rc32k_reg_reg = i;
//        delayUs(10000,HIGH_CLOCK);
//        regVal = PMU->pmu_pmu_state & 0xffff;
//        //save ./rc32k_cali.hex 0x20010000,0x20010100
//        *((uint32*)(0x20010000 + i*4)) = regVal;
//        //printf("cali:reg=%d, result=%d\r\n",i, regVal);
//    }

    // rc32k calibration.
    PMU->pmu_rc32k_calibration_reg = 0x0;   //using the smallest coef.
    delayUs(100,HIGH_CLOCK);                //delay 1 cycle making this coef active.
    index = 0;                              //index is from 0 ~ 63. the larger index means the higher frequency.

    for(i=5; i>=0; i=i-1) {
        // try setting different bits to 1, from bit5 to bit0.
        index |= 1<<i;
        // exchange index to register.
        if(index >= 0x20) {
            regVal = index - 0x20;
        }
        else {
            regVal = (~index) & 0xff ;
        }
        RFC->rf_rc32k_reg_reg = regVal;
        delayUs(100,HIGH_CLOCK);

        // read period of clock 32k.
        regVal = PMU->pmu_pmu_state & 0xffff;

        // if period is less than our target, then clear this bit.
        if(regVal < 0x5f5e)        {
            index &= ~(1<<i);
        }
    }

    // set as regular coef.
    PMU->pmu_rc32k_calibration_reg = 0x5;
}

/**
 * @brief   ADC raw data output,  via P2(clk), P18~P7(bit[11:0]), P19(head).
               : 12bit format, please refer to pin mux excel document for more details. .
 * @param   enable: 1: enable.  0: disable.
 * @return  None.
 * @note
 */
void adcRawOutput(int enable)
{
    // comment this setting, so for all HIGH_CLOCK(50 or 125mhz) and ADC_SAMPLE_RATE(8.33 or 16.67) cases, the raw data has the same sequence. 
    // The sequence is: 
    // Head: 1       0        0         0        X           ...    X              1       0        0         0        X             ...      X          
    // data: rx0.i   rx0.q    rx1.i     rx1.q    don't care  ...    don't care     rx0.i   rx0.q    rx1.i     rx1.q    don't care    ...      don't care

    if(enable)
    {
        // adc raw data output via P2(clk), P18~P7(bit[11:0]), P19(head). 
        for(int i=7;i<20;i++)
        {
            *((uint32*)(GPIO_REGS + i + 12)) = 0x5 | 1<<9 | 1<<10;   //set as function 5 (12bit adc output) with maximum drive strength: 12mA. 
        }
        
        // hclkOutputP02
        GPIO->gpio_p02_config = 5|1<<9|1<<10;
        PMU->pmu_clk_gate_reg |= pmu_clk_gate_reg_ctrl_clk_adc_test_12b_en_bit;  
    }
    else
    {
        // all high-z. 
        for(int i=7;i<20;i++)
        {
            *((uint32*)(GPIO_REGS + i + 12)) = 0x10;  //high-z
        }
        
        // hclkOutputP02
        GPIO->gpio_p02_config = 0x10;
        PMU->pmu_clk_gate_reg &= ~pmu_clk_gate_reg_ctrl_clk_adc_test_12b_en_bit;        
    }   
}

////--- active.  50mhz: 9.6mA 
//void pmuActiveTest(void)
//{
//    //--- MUST enable all of clock gating cells. Otherwise, the sleep will fail.
//    PMU->pmu_reg_ext_clk_en_reg = 0x0 ;

//    setInterrupt(INT_UART1, ENABLEINT);  //disable uart1.
//    
//    for(int i=0;i<31;i++){
//        *((uint32*)(GPIO_REGS + i + 12)) = 0x50; 
//    }
//    *((uint32*)(GPIO_REGS + 4 + 12)) = 0x90;  //p04 pullup + high-z. 
//    //*((uint32*)(GPIO_REGS + 22 + 12)) = 0x50;  //p22 pulldown + high-z. 
//    //*((uint32*)(GPIO_REGS + 29 + 12)) = 0x50;  //p29 pulldown + high-z. 

//    RFC->rfc_xo50m_cfg_reg = 0x888; 
//    RFC->rf_plli_daca_reg = 0x0;
//    PMU->pmu_clk_gate_reg = 0x0;
//    PMU->pmu_pmu_ctrl_reg |= pmu_pmu_ctrl_reg_manu_ctrl_en_bit | pmu_pmu_ctrl_reg_ctrl_ldo12_pd_bit;
//    
//    if(1){
//        while(1);
//    }
//    else {
//        // test stability for the switch. 
//        while(1)
//        {
//            for(int i=0;i<10000;i++);
//            gpioOutput(21,0);
//            RFC->rfc_xo50m_cfg_reg = 0x8f8; 
//            RFC->rf_plli_daca_reg = 0x14aaa8;
//            PMU->pmu_pmu_ctrl_reg &=  ~pmu_pmu_ctrl_reg_ctrl_ldo12_pd_bit;   
//            
//            for(int i=0;i<10000;i++);
//            gpioOutput(21,1);   
//            RFC->rfc_xo50m_cfg_reg = 0x888; 
//            RFC->rf_plli_daca_reg = 0x0;
//            PMU->pmu_pmu_ctrl_reg |=  pmu_pmu_ctrl_reg_ctrl_ldo12_pd_bit;            
//        }
//    }
//}

////--- idle,  50mhz:  5.5mA  
//void pmuIdleTest(void)
//{
//    //--- MUST enable all of clock gating cells. Otherwise, the sleep will fail.
//    PMU->pmu_reg_ext_clk_en_reg = 0x0 ;

//    setInterrupt(INT_UART1, ENABLEINT);  //disable uart1.
//    
//    for(int i=0;i<31;i++){
//        *((uint32*)(GPIO_REGS + i + 12)) = 0x50; 
//    }
//    *((uint32*)(GPIO_REGS + 4 + 12)) = 0x90;  //p04 pullup + high-z. 
//    //*((uint32*)(GPIO_REGS + 22 + 12)) = 0x50;  //p22 pulldown + high-z. 
//    //*((uint32*)(GPIO_REGS + 29 + 12)) = 0x50;  //p29 pulldown + high-z. 

//    mcuGotoIdle();
//}

////--- Sleep,   100uA  
//void pmuSleepTest(void)
//{
//    adt3102SystemInit();
//    
//    // sleep configuation. 
//    mcuSleepConfig(0);
//    
//    // set all GPIOs as pulldown + high-z, except P04 and P11 which are pulled up by PCB.  
//    for(int i=0;i<31;i++){
//        *((uint32*)(GPIO_REGS + i + 12)) = 0x50; 
//    }
//    *((uint32*)(GPIO_REGS + 4 + 12)) = 0x90;  //p04 pullup + high-z. 
//    *((uint32*)(GPIO_REGS + 11 + 12)) = 0x90;  //p11 pullup + high-z. 
//   
//    // goto sleep without wakeup. 
//    mcuGotoSleep();
//    while(1);    
//}
